package cn.assumejson.pro_netty.netty.client;

import cn.assumejson.pro_netty.constant.Constants;
import cn.assumejson.pro_netty.netty.client.asyn.RequestFuture;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.nio.charset.StandardCharsets;

import static cn.assumejson.pro_netty.utils.GsonUtil.gson;

/**
 * @author by gang.Li 2022/3/12 11:47
 */
public class NettyClient {
    public static EventLoopGroup group = new NioEventLoopGroup();

    public static Bootstrap getBootstrap() {
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.group(group);
        // s设置内存分配器
        bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        ClientHandler handler = new ClientHandler();

        // 将handler 添加pipeline中
        bootstrap.handler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel ch) throws Exception {
                ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,
                        0, 4, 0, 4));
                ch.pipeline().addLast(new StringDecoder());
                ch.pipeline().addLast(handler);
                ch.pipeline().addLast(new LengthFieldPrepender(4, false));
                ch.pipeline().addLast(new StringEncoder(StandardCharsets.UTF_8));
            }
        });
        // 连接服务器
        ChannelFuture cf = bootstrap.connect("127.0.0.1", Constants.port);

        return bootstrap;
    }


    /**
     * send request
     *
     * @param msg msg
     * @return result
     */
    public static Object sendRequest(Object msg) {

        // 构建request 请求
        RequestFuture res = new RequestFuture();
        res.setRequest(msg);
        ChannelFuture cf = null;
        try {
            cf = ChannelFutureManager.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        assert cf != null;
        cf.channel().writeAndFlush(gson.toJson(msg));
        return res.get();
    }

    /**
     * 根据构造的请求参数发送请求
     *
     * @param requestFuture requestFuture
     * @return Object
     */
    public static Object sendRequest(RequestFuture requestFuture) {

        ChannelFuture cf = null;
        try {
            cf = ChannelFutureManager.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        assert cf != null;
        cf.channel().writeAndFlush(gson.toJson(requestFuture));
        return requestFuture.get();
    }

    /**
     * 访问制定路径的网络接口
     *
     * @param msg  msg
     * @param path path
     * @return Object
     */
    public Object sendRequest(Object msg, String path) {
        // 构建request 请求
        RequestFuture res = new RequestFuture();

        res.setRequest(msg);
        res.setPath(path);
        String requestStr = gson.toJson(res);
        ChannelFuture cf = null;
        try {
            cf = ChannelFutureManager.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        assert cf != null;
        cf.channel().writeAndFlush(requestStr);
        return res.get();
    }

    public static void main(String[] args) {
        NettyClient nettyClient = new NettyClient();
        for (int i = 0; i < 100; i++) {
            Object result = nettyClient.sendRequest("id" + i, "getUserNameById");
            System.out.println(result);
        }
    }
}
